#ifndef _Serializer_h__
#define _Serializer_h__

#include <buildspec.h>


#include <Client/ClientUtils/Network/NetworkInterface.h>

namespace GST {

	namespace exceptions
	{
		/**
		  * Base class for test's performed by Serializer::TestInsertIsValid()
		  */
		class FeatureClassInsertIsInvalid
			: public GSTRuntimeException
		{
		public:
			FeatureClassInsertIsInvalid(const std::string & throwLocation, const std::string & msg) 
				: GSTRuntimeException(throwLocation, msg)
			{}

			virtual ~FeatureClassInsertIsInvalid() throw()
			{}
		};

		/**
		  * if owner specified in the class is not available for the current logged on user.
		  *
		  *	Potential reasons this check failed:
		  *	<ol>
		  *		<li> User is different
		  *		<li> User is not in the group
		  * </ol>
		  */
		class OwnerNotAvailable
			: public FeatureClassInsertIsInvalid
		{
		public:
			std::string ownerStr;
			bool ownerIsGroup;

			OwnerNotAvailable(const std::string & throwLocation, const std::string & ownerStr, bool ownerIsGroup) 
				: FeatureClassInsertIsInvalid(throwLocation, "OwnerNotAvailable")
				, ownerStr(ownerStr), ownerIsGroup(ownerIsGroup)
			{}

			virtual ~OwnerNotAvailable()  throw()
			{}
		};

		/**
		  * if feature class is still in use
		  */
		class FeatureClassInUse
			: public FeatureClassInsertIsInvalid
		{
		public:
			std::string featureClassName;

			FeatureClassInUse(const std::string & throwLocation, const std::string & featureClassName) 
				: FeatureClassInsertIsInvalid(throwLocation, "FeatureClassInUse")
				, featureClassName(featureClassName)
			{}

			virtual ~FeatureClassInUse() throw()
			{}
		};

		/**
		  * if the srs specified in class is not available at the current connection
		  */
		class SRSNotAvailable
			: public FeatureClassInsertIsInvalid
		{
		public:
			std::string srsIdentifier;

			SRSNotAvailable(const std::string & throwLocation
				, const std::string & message
				, const std::string & srsIdentifier) 
				: FeatureClassInsertIsInvalid(throwLocation, message)
				, srsIdentifier(srsIdentifier)
			{}

			virtual ~SRSNotAvailable() throw()
			{}
		};

		/**
		  *  if the feature class as constrained object properties, but the linked table is not available
		  */
		class SourceTableNotAvailable
			: public FeatureClassInsertIsInvalid
		{
		public:
			std::string sourceTableName;
			std::string errorReport;

			SourceTableNotAvailable(const std::string & throwLocation, const std::string & sourceTableName, const std::string & errorReport) 
				: FeatureClassInsertIsInvalid(throwLocation, "SourceTableNotAvailable")
				, sourceTableName(sourceTableName), errorReport(errorReport)
			{}

			virtual ~SourceTableNotAvailable() throw()
			{}
		};

		/**
		  * if the feature class as constrained object properties, linked table exists but some columns are not available
		  */
		class SourceColumnNotAvailable
			: public FeatureClassInsertIsInvalid
		{
		public:
			std::string sourceTableName;
			std::string columnName;
			std::string errorReport;

			SourceColumnNotAvailable(const std::string & throwLocation, const std::string & sourceTableName, const std::string & columnName, const std::string & errorReport) 
				: FeatureClassInsertIsInvalid(throwLocation, "SourceTableNotAvailable")
				, sourceTableName(sourceTableName), columnName(columnName), errorReport(errorReport)
			{}

			virtual ~SourceColumnNotAvailable() throw()
			{}
		};


	} // namespace exception

namespace ClientUtils {

class GST_API_EXPORT Serializer
{
public:
	static void FeatureClassDescsToFile(const std::string & fileName, FeatureClassDetailedDescListPtr featureClasses);
	static FeatureClassDetailedDescListPtr FeatureClassDescsFromFile(const std::string & fileName);

	/**
	  * Performs checks if featureClass can be inserted to the database.
	  * @throws FeatureClassInsertIsInvalid		if a check failed (this is the base class. catch the subclasses to identify which check fails)
	  *	@throws OwnerNotAvailable				if owner specified in the class is not available for the current logged on user.
	  * @throws FeatureClassInUse				if feature class is still in use
	  * @throws SRSNotAvailable					if the srs specified in class is not available at the current connection
	  * @throws SourceTableNotAvailable			if the feature class as constrained object properties, but the linked table is not available
	  * @throws SourceColumnNotAvailable		if the feature class as constrained object properties, linked table exists but some columns are not available
	  *
	  * Pass the parameters owners, featureClasses, srsList if you call this method multiple time. This prevents from querying them on each call.
	  *
	  * \code
	  OwnerListPtr owners = connection->GetOwners();
	  FeatureClassDescListPtr featureClasses = connection->ListFeatureClasses();
	  SRSItemDescListPtr srsList = connection->ListAllSRS();
	  TestInsertIsValid(featureClass, connection, owners, featureClasses, srsList);
	  * \endcode
	  */
	static void TestInsertIsValid(FeatureClassDetailedDescPtr featureClass
		, NetworkPtr connection
		, OwnerListPtr owners = OwnerListPtr()
		, FeatureClassDescListPtr featureClasses = FeatureClassDescListPtr()
		, Geometry::SRSItemDescListPtr srsList = Geometry::SRSItemDescListPtr() );

protected:
	static void TestConstrainedProperty(TableConstrainedAttributeDescPtr cp
		, NetworkPtr connection); 
};	


} //namespace ClientUtils
} //namespace GST

#endif // _Serializer_h__
